package drds.global_transaction.api.message_codec;

import io.netty.buffer.ByteBuf;
import lombok.Getter;
import lombok.Setter;

import java.nio.ByteBuffer;

public abstract class ResponseMessage extends Message
{
	private static final long serialVersionUID = 1L;
	@Setter
	@Getter
	private ResponseCode responseCode;
	@Setter
	@Getter
	private String message;

	//
	@Override
	public boolean decode(ByteBuf byteBuf)
	{
		int readableBytes = byteBuf.readableBytes();
		if (readableBytes < 1)
		{
			return false;
		}
		this.setResponseCode(ResponseCode.get(byteBuf.readByte()));
		readableBytes--;
		if (responseCode == ResponseCode.failed)
		{
			if (readableBytes < 2)
			{
				return false;
			}
			short length = byteBuf.readShort();
			readableBytes -= 2;
			if (readableBytes < length)
			{
				return false;
			}

			if (length > 0)
			{
				byte[] bytes = new byte[length];
				byteBuf.readBytes(bytes);
				this.setMessage(new String(bytes, UTF8));
			}
		}
		return true;
	}

	@Override
	public void decode(ByteBuffer byteBuffer)
	{
		this.setResponseCode(ResponseCode.get(byteBuffer.get()));
		if (responseCode == ResponseCode.failed)
		{
			short length = byteBuffer.getShort();
			if (length > 0)
			{
				byte[] bytes = new byte[length];
				byteBuffer.get(bytes);
				this.setMessage(new String(bytes, UTF8));
			}
		}
	}

	//
	public ByteBuffer putBytesToByteBuffer()
	{
		ByteBuffer byteBuffer = createByteBuffer();
		byteBuffer.put((byte) responseCode.ordinal());
		if (responseCode == ResponseCode.failed)
		{
			if (getMessage() != null)
			{
				String message;
				if (getMessage().length() > 128)
				{
					message = getMessage().substring(0, 128);
				} else
				{
					message = getMessage();
				}
				byte[] bytes = message.getBytes(UTF8);
				if (bytes.length > 400 && getMessage().length() > 64)
				{
					message = getMessage().substring(0, 64);
					bytes = message.getBytes(UTF8);
				}
				byteBuffer.putShort((short) bytes.length);
				if (bytes.length > 0)
				{
					byteBuffer.put(bytes);
				}
			} else
			{
				byteBuffer.putShort((short) 0);
			}
		}
		//
		markAsEncode();
		return byteBuffer;
	}

}
